// 文件: server/Shares.Infrastructure/Nacos/ConfigurationListenerBase.cs
// -----------------------------------------------------------------------
//  <copyright file="ConfigurationListenerBase.cs" company="LiuliuSoft">
//      Copyright (c) 2025 66SOFT. All rights reserved.
//  </copyright>
//  <site>https://ifs.66soft.net</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-10-03 12:10</last-date>
// -----------------------------------------------------------------------

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Nacos.V2;
using System.Text.Json;

using DaprPlus.Configurations;


namespace Shares.Infrastructure.Nacos;

/// <summary>
/// Nacos配置监听基类
/// </summary>
public abstract class ConfigurationListenerBase(
    IServiceProvider provider)
    : BackgroundService
{
    protected ILogger Logger { get; } = provider.GetLogger<ConfigurationListenerBase>();

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Logger.LogInformation("Starting configuration listener: {ListenerType}", GetType().Name);

        var configService = provider.GetRequiredService<INacosConfigService>();
        try
        {
            // 获取需要监听的配置列表
            var configs = GetConfigurationItems();

            foreach (var config in configs)
            {
                var listener = new ConfigurationListener(this, config.DataId, config.Group);
                await configService.AddListener(
                    config.DataId,
                    config.Group,
                    listener);

                Logger.LogInformation("Listening to configuration: {DataId} in group {Group}",
                    config.DataId, config.Group);
            }
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "Failed to start configuration listener");
        }
    }

    /// <summary>
    /// 获取需要监听的配置项列表
    /// </summary>
    /// <returns></returns>
    protected abstract IEnumerable<ConfigurationItem> GetConfigurationItems();

    /// <summary>
    /// 配置变化时的处理逻辑
    /// </summary>
    /// <param name="dataId">配置ID</param>
    /// <param name="group">配置组</param>
    /// <param name="content">配置内容</param>
    public virtual async Task OnConfigurationChanged(string dataId, string group, string content)
    {
        Logger.LogInformation("Configuration changed: {DataId} in group {Group}", dataId, group);

        try
        {
            // 根据配置类型分发处理
            await HandleConfigurationChange(dataId, group, content);
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "Failed to handle configuration change for {DataId}", dataId);
        }
    }

    /// <summary>
    /// 处理具体的配置变化
    /// </summary>
    /// <param name="dataId">配置ID</param>
    /// <param name="group">配置组</param>
    /// <param name="content">配置内容</param>
    protected abstract Task HandleConfigurationChange(string dataId, string group, string content);

    /// <summary>
    /// 解析JSON配置
    /// </summary>
    /// <typeparam name="T">配置类型</typeparam>
    /// <param name="content">配置内容</param>
    /// <returns></returns>
    protected T ParseConfiguration<T>(string content) where T : class
    {
        try
        {
            return JsonSerializer.Deserialize<T>(content) ?? throw new InvalidOperationException("Configuration is null");
        }
        catch (JsonException ex)
        {
            Logger.LogError(ex, "Failed to parse configuration as {Type}", typeof(T).Name);
            throw;
        }
    }

    /// <summary>
    /// 通知配置变化
    /// </summary>
    /// <typeparam name="T">配置类型</typeparam>
    /// <param name="dataId">配置ID</param>
    /// <param name="config">配置对象</param>
    protected async Task NotifyConfigurationChange<T>(string dataId, T config) where T : class
    {
        try
        {
            // 获取所有配置变化处理器
            var handlers = provider.GetServices<IConfigurationChangeHandler<T>>();

            foreach (var handler in handlers)
            {
                try
                {
                    await handler.OnConfigurationChanged(dataId, config);
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Handler {HandlerType} failed to process configuration change",
                        handler.GetType().Name);
                }
            }
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "Failed to notify configuration change for {DataId}", dataId);
        }
    }
}